/*
 *  ======== audio.c ========
 *
 *  This example demonstrates the use of LIO drivers with PIPs and
 *  the lio_pip adapter code. The application performs a loopback, that
 *  is audio data is read from one PIP connected to an input LIO
 *  channel, the the data is written back out on a PIP connected to an
 *  output LIO channel.
 *
 *  The following objects need to be created in the DSP/BIOS
 *  configuration for this application:
 *
 *  * A SWI object named swiEcho. Configure the function as _echo,
 *    and the mailbox value as 3.
 *
 *  * 2 PIP objects, one named pipTx, the other pipRx. The length of the
 *    buffers should be the same and can be any size. See the comments
 *    by the declarations below of pipTx and pipRx for the writer and
 *    reader notify function settings.
 *
 *  * A LOG object named trace, used for status and debug output. Can be
 *    any size and can be circular or fixed.
 */



#include <std.h>

#include <log.h>
#include <sio.h>
#include <swi.h>
#include <que.h>
#include <sem.h>
#include <mem.h>

#include <lio.h>
#include "plio.h"
//#include <stdlib.h>
#include <sys.h>

#include <tsk.h>
#include <sts.h>


#include "synchronization.h"
/*
extern HST_Obj RTA_fromHost;
extern HST_Obj RTA_toHost;
extern SWI_Obj KNL_swi;
extern TSK_Obj TSK_idle;*/
extern TSK_Obj streamTask;
//extern LOG_Obj LOG_system;
extern LOG_Obj trace;
extern LOG_Obj myLog;
extern SIO_Obj inputStream;
extern SIO_Obj outputStream;
//extern STS_Obj IDL_busyObj;
//extern void CSL_cfgInit();

SIO_Handle input = &inputStream;    /* input stream handle */
SIO_Handle output = &outputStream;  /* output stream handle */
Void doStreaming(Arg nloops_arg);    /* function body for streamTask thread */


void main()
{
	/* idle loop */
	return;
}


/*
 *  ======== doStreaming ========
 *  This function forms the body of the TSK thread streamTask which
 */
Void doStreaming(Arg nloops_arg)
{
    Int i, nbytes;
    Int nloops = ArgToInt (nloops_arg);
#if _FLOAT_
    Float *buf;
#else
    Int *buf;
#endif

    if ( SIO_staticbuf(input, (Ptr *)&buf) == 0) {
        SYS_abort("Error reading buffer ");
    }
    
    for (i = 0; i < nloops; i++) {
        if ((nbytes = SIO_get(input, (Ptr *)&buf)) < 0) {
            SYS_abort("Error reading buffer %d", i);
        }
        if (SIO_put(output, (Ptr *)&buf, nbytes) < 0) {
            SYS_abort("Error writing buffer %d", i);
        }
    }
    LOG_printf(&trace, "End SIO example #2");
}



















#if 0
extern QUE_Obj QUEReader;
extern SEM_Obj SEM_QUEReader;

typedef struct MsgObj {
    QUE_Elem    elem;      /* first field for QUE */
    unsigned int val;       /* message value */
} MsgObj, *Msg;

/* Set CONTROLLER_FXN_TABLE in the linker command file. */
extern LIO_Fxns CONTROLLER_FXN_TABLE;
static LIO_Fxns *controller = &CONTROLLER_FXN_TABLE;

extern far LOG_Obj trace; /* application printf() log, any size */ 
extern far PIP_Obj pipRx; /* writerNotify -> PLIO_rxPrime(plioRx)
                           * readerNotify -> SWI_andn(swiEcho,1) */
extern far PIP_Obj pipTx; /* writerNotify -> SWI_andn(swiEcho,2)
                           * readerNotify -> PLIO_txPrime(plioTx) */
extern far SWI_Obj swiEcho; /* SWI object which runs when buffers are ready. */
extern far SWI_Obj swiValidate; /* SWI object which runs when buffers are ready. */

/*
 *  'plioRx' and 'plioTx' objects will be initialized by PLIO_new(). 
 */
PLIO_Obj plioRx, plioTx;

//void validateQUE(void);


/*
 *  ======== main ========
 */

unsigned short buffer[SYN_NSAMPLES];
unsigned int sizeBuffer;

void main()
{
	unsigned int i;

	for (i=0; i< SYN_NSAMPLES; i++)
		buffer[i] = 0;

	sizeBuffer = 0;
    /*
     * CONTROLLER_init() initializes the device controller.
     * See CONTROLLER_init() in the linker command file.
     */ 
    CONTROLLER_init();
    
    /*
     * CONTROLLER_setup() configures device with parameter.
     * If NULL is specified then the default settings will be used.
     * Set CONTROLLER_setup() in the linker command file.
     * The LIO controller comes from the BSL lib (ex. c5400\dsk5416\lib).
     */
    CONTROLLER_setup(NULL);

    /* Bind the PIPs to LIO channels */
    PLIO_new(&plioRx, &pipRx, LIO_INPUT, controller, NULL);
    PLIO_new(&plioTx, &pipTx, LIO_OUTPUT, controller, NULL);

    /*
     * Prime the transmit side with buffers of silence.
     * The transmitter should be started before the receiver.
     * This results in input-to-output latency being one full
     * buffer period if the pipes is configured for 2 frames.
     */
    PLIO_txStart(&plioTx, PIP_getWriterNumFrames(&pipTx), 0);

    /* Prime the receive side with empty buffers to be filled. */
    PLIO_rxStart(&plioRx, PIP_getWriterNumFrames(&pipRx));

    LOG_printf(&trace, "Audio using PIP, LIO and BSL started!"); 


	/* go to the task loop */
//	validateQUE();


    /* exit from main into the DSP/BIOS idle loop */
}



/*
 *  ======== echo ========
 *
 *  This function is executed from the swiEcho DSP/BIOS SWI thread created
 *  statically with the DSP/BIOS configuration tool. The PLIO adapter
 *  posts the swi when an the input PIP has a buffer of data and the
 *  output PIP has an empty buffer to put new data into. This function
 *  copies from the input PIP to the output PIP. You could easily
 *  replace the copy function with signal processing code.
 */
/*Void echo(Void)
{
}*/


Void echo(Void)
{
    Int i, size;
    unsigned short *src, *dst;
	unsigned static long elements = 0;
    Msg         msg;

    /*
     * Check that the precondions are met, that is pipRx has a buffer of
     * data and pipTx has a free buffer.
     */
    if (PIP_getReaderNumFrames(&pipRx) <= 0) {
        LOG_error("echo: No reader frame!", 0);
        return;
    }
    if (PIP_getWriterNumFrames(&pipTx) <= 0) {
        LOG_error("echo: No writer frame!", 0);
        return;
    }

    /* get the full buffer from the receive PIP */
    PIP_get(&pipRx);
    src = PIP_getReaderAddr(&pipRx);
    size = PIP_getReaderSize(&pipRx) * sizeof(short);

    /* get the empty buffer from the transmit PIP */
    PIP_alloc(&pipTx);
    dst = PIP_getWriterAddr(&pipTx);

    /* 
     * Do the data move. Mask off the low bit for compatibility with
     * those codecs that interpret a low bit of '1' as a command flag. 
     */
    for (i = 0; i < size; i++) {
        /* enqueue message */
 //       msg = MEM_alloc(0, sizeof(MsgObj), 0);
        msg = MEM_alloc(0, sizeof(MsgObj), 0);
        if (msg != MEM_ILLEGAL) {
	        //    SYS_abort("Memory allocation failed!\n");
	        /* fill in value */
	        msg->val = *src;

	        /* enqueue message */
	        QUE_put(&QUEReader, msg);

			SEM_post(&SEM_QUEReader);

			elements++;
		}
		else
		{
//			SYS_abort("oohh...");
		}
		/* copy the in to the out */
		*dst++ = *src++;
	} 

    /* Record the amount of actual data being sent */
    PIP_setWriterSize(&pipTx, PIP_getReaderSize(&pipRx));

    /* Free the receive buffer, put the transmit buffer */
    PIP_free(&pipRx);
    PIP_put(&pipTx);
}


/*SWI that gets values from the que and looks for hidden messages*/
Void validateQUE (Void)
{
//    unsigned short value;
    Msg         msg;
	unsigned int nrecieved = 0;
//    Int         i;
	while (nrecieved<SYN_NSAMPLES-1) /* not start validating until samples are enough */
	{
	//	 while (QUE_empty(&QUEReader)) {}; /* wait for a value */

		SEM_pend(&SEM_QUEReader, SYS_FOREVER);

		/* dequeue message */
		msg = QUE_get(&QUEReader);

		/* buffer circular */
		if (++sizeBuffer >= SYN_SIZE)
		{
			sizeBuffer=0;
		}
		buffer[sizeBuffer] = msg->val;
        MEM_free(0, msg, sizeof(MsgObj));

		nrecieved++;
	}

	for(;;)
	{
		/* The queue should never be empty */
//		while (QUE_empty(&QUEReader)) {}; /* wait for a value */
		SEM_pend(&SEM_QUEReader, SYS_FOREVER);
/*		if (QUE_empty(&queue)) {
		    SYS_abort("queue error\n");
		}*/

		/* dequeue message */
		msg = QUE_get(&QUEReader);

		/* buffer circular */
		if (++sizeBuffer >= SYN_NSAMPLES)
		{
			sizeBuffer=0;
		}
		buffer[sizeBuffer] = msg->val;
        MEM_free(0, msg, sizeof(MsgObj));

		if (getSynMark(buffer) == 0)
			LOG_printf(&trace,"un 0!!!");
		else 
			LOG_printf(&trace,"un 1!!!");
		//testSynMark(buffer,sizeBuffer);
	}
}


#endif